import React, { useCallback, useEffect, useState, memo, useMemo, useRef } from 'react';
import { Select as AntdSelect, Tooltip } from 'antd';
import { SelectProps as AntdSelectProps } from 'antd/lib/select';
import { valueType } from 'antd/lib/statistic/utils';
import { SelectProps } from './interface';
import { getData } from './Api';
import { handleChange, handleValue, evalJsStr, setInitExtra } from './util';
import { parse } from './../../utils/json/json';
import QueryProps from '../../interface/apiQuery';
import Icon from './../icon/Icon';
import style from './printTemplateSelect.module.scss';
// import { userInfo } from 'src/pages/approvalAuth/ApprovalAuth';

const { Option } = AntdSelect;

type PrintTemplateSelectProps = {
  functionCode?: string;
  resetTop?: boolean;
};

// const fieldNames = { label: 'name', value: 'id' };
const userInfo = sessionStorage.userInfo ? JSON.parse(sessionStorage.userInfo) : {};
const telentCode = userInfo.Tenant?.tenantCode;

const T = window.$app.t;

const Select: React.FC<SelectProps & AntdSelectProps<valueType> & PrintTemplateSelectProps> = (props) => {
  const isInitRef = useRef(false);
  const isGetData = useRef(false); // 标记是否请求过数据
  const lastQuery = useRef<any>(null);
  const searchTimeout = useRef<any>(null);
  const [data, setData] = useState<Record<string, any>[]>([]);
  const [mockData, setMockData] = useState<Record<string, any>[]>([]);
  const [showSelect, setShowSelect] = useState(false);
  const [loading, setLoading] = useState(false);

  const {
    fieldNames: propFieldNames,
    cacheKey,
    id,
    extra,
    onChange,
    url,
    query,
    isTooltip,
    functionCode,
    ...selectProps
  } = props;

  const fieldNames = useMemo(() => {
    return propFieldNames || { label: 'name', value: 'id' };
  }, [propFieldNames]);

  const handleQueryBeforeGetData = useCallback(
    (queryObj) => {
      let queryObjCopy = { ...(queryObj || {}) };
      if (selectProps.handleQuery) {
        queryObjCopy = selectProps.handleQuery(queryObjCopy);
      }

      return queryObjCopy;
    },
    [selectProps.handleQuery]
  );

  const initReq = async () => {
    isGetData.current = true;

    // if (!url) return;

    getData(
      {
        url: '/bk/api/companyx/PlotConfiguration/findOne',
        query: {
          include: [{ model: 'PlotConfigurationDetail' }],
          where: {
            moduleCode: 'workflow'
          }
        },
        cacheKey,
        rtnDataAfter: props.rtnDataAfter
      },
      (result: any) => {
        // let temp: Record<string, any> = {};

        // for (let i of result) {
        //   const value = evalJsStr(i, fieldNames.value);
        //   temp[value] = i;
        // }

        // const data = Object.values(temp);

        const data = (result.template || []).concat(
          result.PlotConfigurationDetails?.find((item: any) => item.functionCode === functionCode)?.template || []
        );

        setData(
          data.map((item: any) => {
            const businessCode = item.type === '10' ? item.id : item.codeValue;
            const birtModelFile =
              item.type === '10' ? businessCode : './' + telentCode + '/' + 'workflow' + '/' + businessCode;
            // const businessName = item.name;

            return {
              ...item,
              // 这里添加的字段是根据之前使用表单模板时的extra、fieldNames
              birtModelFile,
              // businessCode,
              // businessName
            };
          })
        );
        if (id) setInitExtra(id, props.value as string, data, fieldNames);
      }
    );
  };

  useEffect(() => {
    // 因为部分场景是拿到数据后才能设置初始值的，所以去掉props.value的限制
    if (!isInitRef.current) {
      initReq();
      // if (fieldNames.label.includes('{{') || props.mode === 'multiple' || props.mode === 'tags' || !props.id) {
      //   initReq();
      // }
      isInitRef.current = true;
    }
  }, [initReq]);

  useEffect(() => {
    if (props.extraInitialValue) {
      if (props.extraInitialValue[0]) {
        const keys = Object.keys(props.extraInitialValue[0]).filter(
          (item) => props.extraInitialValue![0][item] !== undefined
        );

        if (keys.length === 2 || (keys.length === 1 && fieldNames.value === fieldNames.label)) {
          setMockData(props.extraInitialValue);
        } else if ((keys.length || (props.value && !keys.length)) && !isGetData.current) {
          initReq();
        }
      }
    }
  }, [props.extraInitialValue, fieldNames, props.value]);

  useEffect(() => {
    if (lastQuery.current && lastQuery.current !== query) {
      if (JSON.stringify(query) !== JSON.stringify(lastQuery.current)) setData([]);
    }
    lastQuery.current = query;
  }, [query]);

  const dataSource = useMemo(() => {
    if (props.dataSource) {
      return typeof props.dataSource === 'string' ? parse(props.dataSource) : props.dataSource;
    }
    return data;
  }, [props.dataSource, data]);

  const _onChange = useCallback(
    (value) => {
      if (id) {
        handleChange({ value, id, dataSource, fieldNames, extra, onChange });
      } else {
        // 非表单使用时，手动处理
        onChange?.(
          dataSource.find((item: any) => item.id === value),
          null as any
        );
      }
    },
    [onChange, dataSource, fieldNames, id, extra]
  );

  const onSearch = useCallback(
    (value) => {
      if (searchTimeout.current) {
        clearTimeout(searchTimeout.current);
        searchTimeout.current = null;
      }

      if (!value) return setData([]);

      searchTimeout.current = setTimeout(async () => {
        const searchQuery: QueryProps = {
          ...query,
          pages: { page: 1, pageSize: 20 },
          fuzzyValue: value,
          fuzzyQuery: true,
          fuzzyField: [fieldNames.value, fieldNames.label]
        };

        searchTimeout.current = null;

        setLoading(true);
        getData({ url: url!, query: handleQueryBeforeGetData(searchQuery) }, (rows: any) => {
          setLoading(false);
          setData(rows);
        });
      }, 500);
    },
    [url, fieldNames, handleQueryBeforeGetData]
  );

  const onFocus = useCallback(() => {
    if (data.length) return;
    setLoading(true);
    initReq();
    isInitRef.current = true;
    setLoading(false);
  }, [data, initReq, url, query]);

  const _dataSource = dataSource.length ? dataSource : mockData;

  const value = useMemo(() => {
    const v = handleValue(props.value, props.mode);
    if (!v) return v;

    const map = _dataSource.map((item: any) => evalJsStr(item, fieldNames.value));
    if (Array.isArray(v)) {
      return v
        .map((ele: any) => {
          if (map.includes(ele)) return ele;
          return;
        })
        .filter((item) => item !== undefined);
    } else {
      if (!map.length || !map.includes(v)) {
        return props.formData ? evalJsStr(props.formData, fieldNames.label) : v;
      }
    }
    return v;
  }, [props.value, props.mode, _dataSource, fieldNames]);

  return (
    <AntdSelect
      suffixIcon={
        showSelect && selectProps.showSearch ? (
          <Icon className={style.searchIcon} icon="search" />
        ) : (
          <Icon className={style.searchIcon} icon="&#xe631;" />
        )
      }
      onDropdownVisibleChange={(e) => setShowSelect(e)}
      {...selectProps}
      showSearch={selectProps.showSearch}
      {...(selectProps.showSearch ? { onSearch: onSearch } : null)}
      filterOption={false}
      // allowClear={!selectProps.required}
      value={(value ?? null) as any}
      // {...(!selectProps.showSearch || selectProps.firstLoad ? { onFocus: onFocus } : null)}
      onFocus={onFocus}
      loading={loading}
      placeholder={props?.placeholder || T('dymb')}
      onChange={_onChange}
      className={`${selectProps.className} ${selectProps.resetTop && style.resetTop}`}
    >
      {_dataSource.map((item: any) => {
        const label = evalJsStr(item, fieldNames.label);

        return (
          <Option key={item.id || item.value} value={evalJsStr(item, fieldNames.value)}>
            {isTooltip ? (
              <Tooltip title={label}>
                <div>{label}</div>
              </Tooltip>
            ) : (
              label
            )}
          </Option>
        );
      })}
    </AntdSelect>
  );
};

export default memo(Select);
